#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#define SYSFS_PATH_BASE    "/sys/devices/platform/tm1629a"
#define SYSFS_BRIGHTNESS   SYSFS_PATH_BASE "/brightness"
#define SYSFS_DISPLAY_ON   SYSFS_PATH_BASE "/display_on"
#define SYSFS_DISPLAY_TEXT SYSFS_PATH_BASE "/display_text"
#define SYSFS_NUM_DIGITS   SYSFS_PATH_BASE "/num_digits"
#define SYSFS_LED_TYPE     SYSFS_PATH_BASE "/led_type"
#define SYSFS_ADDR_MODE    SYSFS_PATH_BASE "/addr_mode"
#define SYSFS_SEGMENTS     SYSFS_PATH_BASE "/segments"

/* 写入sysfs文件 */
static int write_sysfs(const char *path, const char *buf)
{
    int fd, ret;

    fd = open(path, O_WRONLY);
    if (fd < 0) {
        printf("无法打开文件: %s (错误: %s)\n", path, strerror(errno));
        return -1;
    }

    ret = write(fd, buf, strlen(buf));
    if (ret < 0) {
        printf("写入失败: %s (错误: %s)\n", path, strerror(errno));
        close(fd);
        return -1;
    }

    close(fd);
    return 0;
}

/* 读取sysfs文件 */
static int read_sysfs(const char *path, char *buf, size_t size)
{
    int fd, ret;

    fd = open(path, O_RDONLY);
    if (fd < 0) {
        printf("无法打开文件: %s (错误: %s)\n", path, strerror(errno));
        return -1;
    }

    ret = read(fd, buf, size - 1);
    if (ret < 0) {
        printf("读取失败: %s (错误: %s)\n", path, strerror(errno));
        close(fd);
        return -1;
    }

    buf[ret] = '\0';
    close(fd);
    return 0;
}

/* 测试显示功能 */
static int test_display(void)
{
    char buf[32];
    int i;

    printf("测试显示功能:\n");

    /* 获取配置信息 */
    printf("设备配置信息:\n");
    if (read_sysfs(SYSFS_NUM_DIGITS, buf, sizeof(buf)) == 0)
        printf("- 数码管数量: %s", buf);
    if (read_sysfs(SYSFS_LED_TYPE, buf, sizeof(buf)) == 0)
        printf("- LED类型: %s", buf);
    printf("\n");

    /* 测试数字显示 */
    printf("1. 显示数字 12345678... ");
    if (write_sysfs(SYSFS_DISPLAY_TEXT, "12345678") < 0)
        return -1;
    printf("完成\n");
    sleep(2);

    /* 测试带小数点显示 */
    printf("2. 显示带小数点数字 123.45... ");
    if (write_sysfs(SYSFS_DISPLAY_TEXT, "123.45") < 0)
        return -1;
    printf("完成\n");
    sleep(2);

    /* 测试多个小数点显示 */
    printf("3. 显示多个小数点 1.2.3.4... ");
    if (write_sysfs(SYSFS_DISPLAY_TEXT, "1.2.3.4") < 0)
        return -1;
    printf("完成\n");
    sleep(2);

    /* 测试16进制显示 */
    printf("4. 显示16进制数字 ABCDEF... ");
    if (write_sysfs(SYSFS_DISPLAY_TEXT, "ABCDEF") < 0)
        return -1;
    printf("完成\n");
    sleep(2);

    return 0;
}

/* 测试亮度控制 */
static int test_brightness(void)
{
    int i;
    char buf[32];

    printf("\n测试亮度控制:\n");

    /* 显示测试数字 */
    write_sysfs(SYSFS_DISPLAY_TEXT, "12345678");

    /* 循环设置不同亮度 */
    for (i = 0; i <= 7; i++) {
        printf("设置亮度级别 %d... ", i);
        snprintf(buf, sizeof(buf), "%d", i);
        if (write_sysfs(SYSFS_BRIGHTNESS, buf) < 0)
            return -1;
        printf("完成\n");
        sleep(1);
    }

    return 0;
}

/* 测试显示开关 */
static int test_display_onoff(void)
{
    printf("\n测试显示开关:\n");

    /* 显示测试数字 */
    write_sysfs(SYSFS_DISPLAY_TEXT, "12345678");
    write_sysfs(SYSFS_BRIGHTNESS, "4");

    /* 关闭显示 */
    printf("关闭显示... ");
    if (write_sysfs(SYSFS_DISPLAY_ON, "0") < 0)
        return -1;
    printf("完成\n");
    sleep(2);

    /* 打开显示 */
    printf("打开显示... ");
    if (write_sysfs(SYSFS_DISPLAY_ON, "1") < 0)
        return -1;
    printf("完成\n");
    sleep(2);

    return 0;
}

/* 测试地址模式 */
static int test_addr_mode(void)
{
    char buf[32];

    printf("\n测试地址模式:\n");

    /* 显示测试数字 */
    write_sysfs(SYSFS_DISPLAY_TEXT, "12345678");

    /* 读取当前模式 */
    printf("当前地址模式: ");
    if (read_sysfs(SYSFS_ADDR_MODE, buf, sizeof(buf)) == 0)
        printf("%s", buf);

    /* 切换到固定地址模式 */
    printf("切换到固定地址模式... ");
    if (write_sysfs(SYSFS_ADDR_MODE, "fixed") < 0)
        return -1;
    printf("完成\n");
    sleep(1);

    /* 切换回自动增加模式 */
    printf("切换回自动增加模式... ");
    if (write_sysfs(SYSFS_ADDR_MODE, "auto") < 0)
        return -1;
    printf("完成\n");
    sleep(1);

    return 0;
}

/* 测试段控制 */
static int test_segments(void)
{
    char buf[256];
    
    printf("\n测试段控制:\n");
    
    /* 清空显示 */
    write_sysfs(SYSFS_DISPLAY_TEXT, "");
    
    /* 显示字母H (A|B|C|F|G) */
    printf("1. 在位置0显示字母H... ");
    if (write_sysfs(SYSFS_SEGMENTS, "0 B|C|E|F|G") < 0)
        return -1;
    printf("完成\n");
    sleep(1);
    
    /* 显示字母E (A|D|E|F|G) */
    printf("2. 在位置1显示字母E... ");
    if (write_sysfs(SYSFS_SEGMENTS, "1 A|D|E|F|G") < 0)
        return -1;
    printf("完成\n");
    sleep(1);
    
    /* 显示字母L (D|E|F) */
    printf("3. 在位置2显示字母L... ");
    if (write_sysfs(SYSFS_SEGMENTS, "2 D|E|F") < 0)
        return -1;
    printf("完成\n");
    sleep(1);
    
    /* 显示字母P (A|B|E|F|G) */
    printf("4. 在位置3显示字母P... ");
    if (write_sysfs(SYSFS_SEGMENTS, "3 A|B|E|F|G") < 0)
        return -1;
    printf("完成\n");
    sleep(1);
    
    /* 读取所有段状态 */
    printf("\n当前段状态:\n");
    if (read_sysfs(SYSFS_SEGMENTS, buf, sizeof(buf)) == 0)
        printf("%s", buf);
    
    /* 测试小数点 */
    printf("\n5. 添加小数点... ");
    if (write_sysfs(SYSFS_SEGMENTS, "1 A|D|E|F|G|P") < 0)  /* E. */
        return -1;
    if (write_sysfs(SYSFS_SEGMENTS, "3 A|B|E|F|G|P") < 0)  /* P. */
        return -1;
    printf("完成\n");
    sleep(2);
    
    /* 清空显示 */
    write_sysfs(SYSFS_DISPLAY_TEXT, "");
    
    return 0;
}

int main(int argc, char *argv[])
{
    printf("TM1629A驱动测试程序\n");
    printf("====================\n\n");

    if (test_display() < 0)
        return 1;

    if (test_brightness() < 0)
        return 1;

    if (test_display_onoff() < 0)
        return 1;

    if (test_addr_mode() < 0)
        return 1;

    if (test_segments() < 0)
        return 1;

    printf("\n所有测试完成!\n");
    return 0;
} 